#include "zad7library.hpp"
#include <cstdlib>
#include <iostream>
#include <math.h>

using namespace std;

namespace amodlisz {

	double f(double t,double x) {
		return -100*x;    		
		//return x*(1-exp(t))/(1+exp(t));
    	}
   
 	double  exact(double t) {
      		return exp(-100*t);
		//return 12*exp(t)/(pow(1+exp(t),2));
	}

		ODE::ODE(double t0, double x0, double T, double(*f)(double,double)){   
			tini=t0;
			ison=x0;
			tend=T;
			sfn=f;
		}

		Euler::Euler(double t0, double x0, double T, double(*fun)(double,double)) : ODE(t0,x0,T,*fun) {}

		double* Euler::function(int n) {   // euler definition 
   	 		double *x = new double [n+1];       //method returns a vector
  	  		double h=1.0/100.0;//(tend-tini)/n;
  	 		x[0]=ison;                                        
  	  		for (int k=0;k<n;k++){	
			x[k+1]=x[k]+h*sfn(tini+k*h, x[k]);
			}
  	  	return x;
 	  	}

		Eulerpc::Eulerpc(double t0, double x0, double T, double(*fun)(double,double)) : ODE(t0,x0,T,*fun) {}

		double* Eulerpc::function(int n) {
   			double*x=new double[n+1];     //allocate the space
   			double  h=1.0/100.0;//(tend-tini)/n;
   			x[0]=ison;
			for(int k=0;k<n;k++) {
			x[k+1]=x[k]+h*sfn(tini+k*h,x[k]);              //predictor
			x[k+1]=x[k]+(h/2.0)*(x[k]+sfn(tini+k*h,x[k]));  //corrector
			}
			return   x;
		}

		RK2::RK2(double t0, double x0, double T, double(*fun)(double,double)) : ODE(t0,x0,T,*fun) {}

		double * RK2::function (int  n) {
			double * x=new  double [n+1];
			double h=1.0/100.0;//(tend-tini)/n;
			x[0]=ison;
			for(int k=0;k<n;k++) {
				double F1=(h*k)*sfn(tini+h*k,x[k]);
				double F2=(h*k)*sfn(tini+h*k+1,x[k]+F1/2.0);
				x[k+1]=x[k]+h*F2;
			}
			return x; 
		}

}
